Проект: якорение DID и VC в HLF (R4)
Черновик для обсуждения с Димой и Ромой. Срез кода: develop 8d4f3df5a + ветка feature/todo-261015-2253-did-signed-ops (2026-10-15). Не реализовано — нужно решение команды.
Что уже есть после ветки
Каждая ревизия DID хранит подпись операции, подписанное тело и
digest/prevDigest(хэш-цепочка).GET /v1/dids/{did}/history/verifyпересчитывает цепочку и подписи, отдаётheadDigest.Внутри сервиса не ловятся: подмена неподписанных ревизий целиком и обрезка хвоста истории. Это и закрывает якорение: в реестре лежит
digestкаждой ревизии, сервис сверяется с ним.
Где HLF сейчас (по коду монорепы)
Доступ к сети — через
blockchain-svc(gRPCInvokeSmartContract/QuerySmartContract, инициализацияCreateClient → SetClientPeers → SetClientChaincodes → SetClientConfig → CreateWallet → SetWalletConfig), образец —poa-svc/internal/service/blockchain.go, повтор — [[KCONT-2248]] (documents-svc).docs-chaincode-svcхранит документы в private data collections (NewPrivateDocsRepository,GetPrivateDataHash). Это и есть SideDB из заметок команды: данные видят только члены коллекции, в world state лежит лишь хэш. Для DID/VC как публичного реестра это не подходит — DID должен резолвиться любым участником канала, статус VC — проверяться любым верификатором.
Предложение
Отдельный чейнкод did-registry, world state
Ключ (composite) | Значение | Кто пишет |
|
| did-svc после записи ревизии |
|
| тот же вызов |
|
| vc-svc при выпуске/отзыве |
Правила в чейнкоде (а не только в сервисе):
prevDigestновой записи ==digestтекущей головы (иначе отказ) — обрезка/подмена истории невозможна без следа в реестре.Для подписанных операций чейнкод проверяет JWS операции (EdDSA/ECDSA — stdlib Go в чейнкоде) по ключу подписанта, взятому из своей же записи DID подписанта. Тогда доверие к did-svc не нужно: чейнкод — независимый проверяющий. Требует хранить в world state и публичные ключи (
didkeys~<did>~<versionId>), без персональных данных — только JWK.Деактивированный DID (
didhead.deactivated) — запись новых версий запрещена.
Содержимое документов в реестр не кладём: только отпечатки и ключи. DID Document персоны (did:i:fl:*) содержит service endpoint на identity-сервис — ПДн там нет, но и класть незачем.
Как did-svc пишет: outbox, а не синхронный вызов
В той же транзакции, что и ревизия, — строка в
did_anchor_outbox (did, version, payload, attempts, anchored_at, last_error).Воркер забирает неотправленные, вызывает
InvokeSmartContract, отмечаетanchored_at.Недоступный HLF не роняет приём операций (как решено для documents-svc в KCONT-2248), но
history/verifyпоказывает для ревизииanchored: false.Режим строгости — по аналогии с
DID_OPERATION_PROOF:DID_ANCHOR=off|async|required(required— операция подтверждается клиенту только после записи в реестр).
Проверка
history/verify дополнительно читает did~<did>~* из реестра (QuerySmartContract) и сверяет digest каждой ревизии: расхождение → broken, отсутствие → unanchored.
Вопросы к команде
Один чейнкод на DID и статусы VC или два? (Предлагаю один
did-registry— проще эндорсмент.)Канал:
org(как docs-chaincode) или отдельный? Политика эндорсмента?Проверять JWS операций в чейнкоде (п. 2) или доверять did-svc? С ГОСТ-подписями в чейнкоде понадобится КриптоПро/cryptosmart на пирах — это аргумент проверять только EdDSA/ECDSA, а ГОСТ (L3, УКЭП) оставить проверке PKI-сервиса.
Identity did-svc в сети: Admin организации (как временно в KCONT-2248) или отдельный через Fabric CA.
bcprovider: cryptosmart-proxyпо умолчанию в blockchain-svc (риск из KCONT-2248) — для did-registry на тестовой сети нуженvanilla.
Объём (оценка)
чейнкод
did-registry(3 функции записи, 2 чтения, проверки 1 и 3; п. 2 — +1 день) — 2–3 дня;outbox + воркер + клиент blockchain-svc в did-svc (по образцу poa-svc/KCONT-2248) — 2 дня;
сверка в
history/verify, тесты, деплой в тестовую сеть ([[KCONT-2244]]) — 1–2 дня.
Журнал изменений
Дата | Перечень изменений | Автор |
2026-11-05 | Перенесён из архива DID-VC-итоги-2026-11-03 без изменения содержания. | Дис |